package com.topscomm.mpm.xxlJob;

/**
 * @author liwanpeng
 * @version 1.0
 * @description: TODO
 * @date 2021/6/18 9:09
 */

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.topscomm.basic.BasicEntity;
import com.topscomm.basic.util.SQLAdapter;
import com.topscomm.cbo.pojo.CboUserEntity;
import com.topscomm.cbo.service.ICboMessageAppService;
import com.topscomm.cbo.service.ICboMessageSysService;
import com.topscomm.cbo.service.impl.CboApprovalNodeInsService;
import com.topscomm.cbo.service.impl.CboUserService;
import com.topscomm.mpm.MpmSystemConst;
import com.topscomm.mpm.pojo.MpmProjectEntity;
import com.topscomm.mpm.pojo.MpmProjectTaskEntity;
import com.topscomm.mpm.service.impl.MpmProjectService;
import com.topscomm.mpm.service.impl.MpmProjectTaskService;
import com.topscomm.mpm.utils.GetContextUtil;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.SpringUtil;
import com.topscomm.pub.util.StringBufferProxy;
import com.topscomm.pub.util.StringUtil;
import com.topscomm.tap.TapService;
import com.topscomm.tap.common.DatacodeCache;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author houyuhang
 * @date 2021/04/13
 * @description: 1、检查我的待办，如果存在待办任务则发送待办提醒。
 * 2、任务计划开始日期前1天，若任务未开始，则通过APP提醒任务责任人。
 * 3、任务计划完成日期提前1天，通过APP提醒任务责任人该任务距计划完成日期还剩1天。
 * @modify:
 */
@JobHandler(value = "backlogRemind")
@Component
public class BacklogRemind extends IJobHandler {
    private static final Logger log = LoggerFactory.getLogger(BacklogRemind.class);
    @Autowired
    private CboApprovalNodeInsService cboApprovalNodeInsService;
    @Autowired
    private CboUserService cboUserService;
    @Autowired
    private ICboMessageSysService cboMessageSysService;
    @Autowired
    private ICboMessageAppService cboMessageAppService;
    @Autowired
    private MpmProjectService mpmProjectService;
    @Autowired
    private MpmProjectTaskService mpmProjectTaskService;

    @Override
    public ReturnT<String> execute(String param) {
        try {
            // 查询所有待办项
            StringBufferProxy whereSql = new StringBufferProxy();
            whereSql.appendSingle(" state = 1 and sourcetype like '%Mpm%' ");
            List<Map<String, Object>> nodeInsList = cboApprovalNodeInsService.queryMapByWhere(whereSql.toString());
            if (CollectionUtil.isEmpty(nodeInsList)) {
                return ReturnT.SUCCESS;
            }
            // 获取人员id对应的姓名和工号
            String cboId = nodeInsList.stream().map(item -> "'" + ConvertUtil.convertToString(item.get("approvaluserid")) + "'").collect(Collectors.joining(","));
            whereSql.clear();
            whereSql.appendSingle(" id in ({0}) ", cboId);
            List<CboUserEntity> cboUserEntities = cboUserService.queryByWhere(whereSql.toString());
            Map<String, List<CboUserEntity>> cboUserMap = cboUserEntities.stream().collect(Collectors.groupingBy(item -> ConvertUtil.convertToString(item.getId())));
            for (Map<String, Object> nodeIns : nodeInsList) {
                Date modifiedon = (Date) nodeIns.get("modifiedon");
                long modifiedontime = modifiedon.getTime();
                long datetime = new Date().getTime();
                long t = (datetime - modifiedontime) / (1000 * 60 * 60);
                // job任务定为工作日9点、执行，最新改动时间和这些时间的差值为2小时，提醒，否则不提醒
                if (t < 2L) {
                    continue;
                }
                // 给审批人发送App提醒
                sendBacklogAppMessage(nodeIns, t, cboUserMap);
            }
            // 任务计划开始日期前1天，若任务未开始，则通过APP提醒任务责任人
            remindTaskStartDate();
            // 任务计划完成日期提前1天，通过APP提醒任务责任人该任务距计划完成日期还剩1天,在任务超期提醒中已实现，不再发送
            // remindTaskEndDate();
            return ReturnT.SUCCESS;
        } catch (Exception e) {
            log.error("发送待办提示失败", e);
            return new ReturnT<>(ReturnT.FAIL_CODE, e.getMessage());
        }
    }

    /**
     * @author: houyuhang
     * @date: 2022-04-09
     * @description:发送待办APP消息提醒
     * @modify:
     */
    public void sendBacklogAppMessage(Map<String, Object> nodeIns, long t, Map<String, List<CboUserEntity>> cboUserMap) {
        DatacodeCache datacodeCache = (DatacodeCache) SpringUtil.getBean("datacodeCache");
        String valueDynamic = datacodeCache.getValueDynamic("CboApprovalFlowCategory", ConvertUtil.convertToString(nodeIns.get("sourcetype")), "code", "name");
        // 获取当前审批节点的项目信息
        String sourcetype = nodeIns.get("sourcetype").toString();
        // 如果该流程为问题、风险、需求流程，则不发送APP提醒
        if (MpmSystemConst.SourcetypeNoApp.contains("," + sourcetype + ",")) {
            return;
        }
        String sourceid = nodeIns.get("sourceid").toString();
        String approvaluserid = nodeIns.get("approvaluserid").toString();
        List<CboUserEntity> cboUserEntities = cboUserMap.get(approvaluserid);
        if (CollectionUtil.isEmpty(cboUserEntities)) {
            return;
        }
        String lowerFirst = Character.toLowerCase(sourcetype.charAt(0)) +
                sourcetype.substring(1);
        String serviceName = lowerFirst + "Service";
        ApplicationContext applicationContext = GetContextUtil
                .getApplicationContext();
        if (!applicationContext.containsBean(serviceName)) {
            return;
        }
        TapService serviceBean = (TapService) SpringUtil.getBean(serviceName);
        BasicEntity selectEntity = serviceBean.queryById(sourceid);
        // 如果该流程已被删除，则不发送消息提醒
        if (ObjectUtil.isEmpty(selectEntity)) {
            return;
        }
        //如果是立项流程的话，直接拼接项目名称即可，否则，就需要通过节点的信息获取到对应业务表的projectcode，在通过projectcode获取到项目名称
        String projectName = mpmProjectService.queryProjectName(serviceName, selectEntity);
        String dispprojectlevel = datacodeCache.getValueDynamic("MpmProjectLevel", mpmProjectService.queryProjectLevel(serviceName, selectEntity), "code", "name");
        // 如果projectname不存在，该项目已被删除，则不发送消息提醒
        if(StringUtil.isEmpty(projectName)) {
            return;
        }
        // 发送APP和系统消息
        String approvalUserContent = "您有【" + dispprojectlevel + "级项目："+ projectName + "】" + valueDynamic + "流程的" + nodeIns.get("dispnodeid") + "节点的待审批工单，" + "审批等待已历时" + t + "小时，请您及时办理。";
        Map<String, Object> appMessageMap = mpmProjectService.insertMessageApp(cboUserEntities.get(0).getCode(), "销售项目审批办理提醒",
                approvalUserContent, ConvertUtil.convertToLong(nodeIns.get("sourceid")), "mpm-backlogRemind", 0);
        cboMessageAppService.insertMap(appMessageMap);
        Map<String, Object> sysMessageMap = mpmProjectService.insertMessageSys(cboUserEntities.get(0).getCode(), cboUserEntities.get(0).getName(),
                "销售项目审批办理提醒", approvalUserContent, ConvertUtil.convertToLong(nodeIns.get("sourceid")), "mpm-backlogRemind");
        cboMessageSysService.insertMap(sysMessageMap);
        // 遍历待办事项，如果有属于立项流程的待办，也给项目经理发送提醒
        sendMessageToPM(nodeIns, t, cboUserEntities);

    }

    /**
     * @author: houyuhang
     * @date: 2022-04-09
     * @description:遍历待办事项，如果有属于立项流程的待办，也给项目经理发送提醒
     * @modify:
     */
    public void sendMessageToPM(Map<String, Object> nodeIns, long t, List<CboUserEntity> cboUserEntities) {
        DatacodeCache datacodeCache = (DatacodeCache) SpringUtil.getBean("datacodeCache");
        if (!"MpmProject".equals(nodeIns.get("sourcetype"))) {
            return;
        }
        StringBufferProxy whereSql = new StringBufferProxy();
        whereSql.appendSingle(" id ='{0}' ", nodeIns.get("sourceid"));
        List<MpmProjectEntity> mpmProjectEntities = mpmProjectService
                .queryByWhere(whereSql.toString());
        MpmProjectEntity mpmProjectEntity = null;
        if (mpmProjectEntities.size() == 0) {
            return;
        } else {
            mpmProjectEntity = mpmProjectEntities.get(0);
        }
        String dispprojectlevel = datacodeCache.getValueDynamic("MpmProjectLevel", mpmProjectEntity.getProjectlevel(),"code", "name");
        //插入App消息和系统消息
        String managercontent = "您有【" + dispprojectlevel + "级项目：" + mpmProjectEntity.getProjectname() + "】项目立项流程的" + nodeIns.get("dispnodeid") + "节点" + cboUserEntities.get(0).getName() + "审批等待已历时" + t + "小时,请及时沟通提醒。";
        Map<String, Object> appMessageMap = mpmProjectService.insertMessageApp(mpmProjectEntity.getProjectmanagercode(), "销售项目审批进度提醒",
                managercontent, mpmProjectEntity.getId(), "mpm-backlogRemind", 0);
        cboMessageAppService.insertMap(appMessageMap);
        Map<String, Object> sysMessageMap = mpmProjectService.insertMessageSys(mpmProjectEntity.getProjectmanagercode(), mpmProjectEntity.getProjectmanager(),
                "销售项目审批进度提醒", managercontent, mpmProjectEntity.getId(), "mpm-backlogRemind");
        cboMessageSysService.insertMap(sysMessageMap);
    }
    /**
     * @author: houyuhang
     * @date: 2022-04-13
     * @description:任务计划开始日期前1天，若任务未开始，则通过APP提醒任务责任人。
     * @modify:
     */
    public void remindTaskStartDate() {
        StringBufferProxy sql = new StringBufferProxy();
        // 获取已下发、未开始且计划开始日期前1天的任务
        sql.appendSingle(" state = 9 and {0} = {1} and {2} = {3} ",
                MpmProjectTaskEntity.FieldTaskstate, MpmSystemConst.TaskStateCode.TaskNotStartCode,
                SQLAdapter.toChar(SQLAdapter.getDate() + ", 'yyyy-mm-dd'"),
                SQLAdapter.toChar(MpmProjectTaskEntity.FieldPlanstartdate + " - 1, 'yyyy-mm-dd'"));
        List<MpmProjectTaskEntity> mpmProjectTaskEntities = mpmProjectTaskService.queryByWhere(sql.toString());
        if (CollectionUtil.isEmpty(mpmProjectTaskEntities)) {
            return;
        }
        // 获取任务对应的项目信息
        String tasksql = sql.toString();
        sql.clear();
        sql.appendSingle(" projectcode in (select projectcode from mpmprojecttask where {0})", tasksql);
        List<MpmProjectEntity> mpmProjectEntities = mpmProjectService.queryByWhere(sql.toString());
        Map<String, MpmProjectEntity> mpmProjectEntityMap = mpmProjectEntities.stream().collect(Collectors.toMap(MpmProjectEntity::getProjectcode, item -> item, (v1, v2) -> v1));
        // 插入App消息和系统消息
        for (MpmProjectTaskEntity mpmProjectTaskEntity : mpmProjectTaskEntities) {
            String managercontent = "【" + mpmProjectEntityMap.get(mpmProjectTaskEntity.getProjectcode()).getProjectname() + "】项目的" + "【" + mpmProjectTaskEntity.getTaskname() + "】任务距计划开始日期还剩1天，请及时处理。";
            Map<String, Object> appMessageMap = mpmProjectService.insertMessageApp(mpmProjectTaskEntity.getResponsiblecode(), "销售项目任务提醒",
                    managercontent, mpmProjectEntityMap.get(mpmProjectTaskEntity.getProjectcode()).getId(), MpmProjectTaskEntity.tableName, 0);
            cboMessageAppService.insertMap(appMessageMap);
            Map<String, Object> sysMessageMap = mpmProjectService.insertMessageSys(mpmProjectTaskEntity.getResponsiblecode(), mpmProjectTaskEntity.getResponsible(),
                    "销售项目任务提醒", managercontent, mpmProjectEntityMap.get(mpmProjectTaskEntity.getProjectcode()).getId(), MpmProjectTaskEntity.tableName);
            cboMessageSysService.insertMap(sysMessageMap);
        }
    }
    /**
     * @author: houyuhang
     * @date: 2022-04-14
     * @description:任务计划完成日期提前1天，通过APP提醒任务责任人该任务距计划完成日期还剩1天。
     * @modify:
     */
    public void remindTaskEndDate() {
        StringBufferProxy sql = new StringBufferProxy();
        // 查询已下发且任务状态处于未开始、进行中且当前时间在任务计划完成日期前1天
        sql.appendSingle(" state = 9 and {0} in ({1}) and {2} = {3} ",
                MpmProjectTaskEntity.FieldTaskstate, MpmSystemConst.TaskStateCode.TaskNotStartCode + "," + MpmSystemConst.TaskStateCode.TaskIncompleteCode,
                SQLAdapter.toChar(SQLAdapter.getDate() + ", 'yyyy-mm-dd'"),
                SQLAdapter.toChar(MpmProjectTaskEntity.FieldPlanenddate + " - 1, 'yyyy-mm-dd'"));
        List<MpmProjectTaskEntity> mpmProjectTaskEntities = mpmProjectTaskService.queryByWhere(sql.toString());
        if (CollectionUtil.isEmpty(mpmProjectTaskEntities)) {
            return;
        }
        // 获取任务对应的项目信息
        String tasksql = sql.toString();
        sql.clear();
        sql.appendSingle(" projectcode in (select projectcode from mpmprojecttask where {0})", tasksql);
        List<MpmProjectEntity> mpmProjectEntities = mpmProjectService.queryByWhere(sql.toString());
        Map<String, MpmProjectEntity> mpmProjectEntityMap = mpmProjectEntities.stream().collect(Collectors.toMap(MpmProjectEntity::getProjectcode, item -> item, (v1, v2) -> v1));
        // 插入App消息和系统消息
        for (MpmProjectTaskEntity mpmProjectTaskEntity : mpmProjectTaskEntities) {
            String managercontent = "【" + mpmProjectEntityMap.get(mpmProjectTaskEntity.getProjectcode()).getProjectname() + "】项目的" + "【" + mpmProjectTaskEntity.getTaskname() + "】任务距计划完成日期还剩1天，请及时处理。";
            Map<String, Object> appMessageMap = mpmProjectService.insertMessageApp(mpmProjectTaskEntity.getResponsiblecode(), "销售项目任务提醒",
                    managercontent, mpmProjectEntityMap.get(mpmProjectTaskEntity.getProjectcode()).getId(), MpmProjectTaskEntity.tableName, 0);
            cboMessageAppService.insertMap(appMessageMap);
            Map<String, Object> sysMessageMap = mpmProjectService.insertMessageSys(mpmProjectTaskEntity.getResponsiblecode(), mpmProjectTaskEntity.getResponsible(),
                    "销售项目任务提醒", managercontent, mpmProjectEntityMap.get(mpmProjectTaskEntity.getProjectcode()).getId(), MpmProjectTaskEntity.tableName);
            cboMessageSysService.insertMap(sysMessageMap);
        }
    }
}
